package com.sea.physical.service.impl;


import com.codecrane.core.util.CountryMoneyEnum;
import com.sea.finance.entity.ExchangeRate;
import com.sea.finance.entity.ExchangeRateRecord;
import com.sea.finance.service.ExchangeRateRecordService;
import com.sea.finance.service.ExchangeRateService;
import com.sea.physical.entity.*;
import com.sea.physical.mapper.CreateDespatchPlanMapper;
import com.sea.physical.service.*;
import com.sea.product.entity.Product;
import com.sea.product.service.ProductService;
import com.sea.supply.entity.Produce;
import com.sea.supply.entity.ProduceDetail;
import com.sea.supply.entity.WareDistribute;
import com.sea.supply.service.ProduceDetailService;
import com.sea.supply.service.ProduceService;
import com.sea.supply.service.WareDistributeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Service
public class CreateDespatchPlanServiceImpl implements CreateDespatchPlanService {

    @Autowired
    private CreateDespatchPlanMapper createDespatchPlanMapper;
    @Autowired
    private CreateDistributeSkuService createDistributeSkuService;
    @Autowired
    private CreateDespatchSkuService createDespatchSkuService;
    @Autowired
    private CreatePlanService createPlanService;
    @Autowired
    private CreateSkuService createSkuService;
    @Autowired
    private ProductService productService;
    @Autowired
    private TaxRateService taxRateService;
    @Autowired
    private CoefficientService coefficientService;
    @Autowired
    private ExchangeRateService exchangeRateService;
    @Autowired
    private FreightService freightService;
    @Autowired
    private ProduceDetailService produceDetailService;
    @Autowired
    private ExchangeRateRecordService exchangeRateRecordService;
    @Autowired
    private CreatePackingSkuService createPackingSkuService;
    @Autowired
    private ProduceService produceService;

    @Autowired
    private CoefficientSkuService coefficientSkuService;


    @Override
    public int save(CreateDespatchPlan createDespatchPlan) {
        return createDespatchPlanMapper.insert(createDespatchPlan);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public  int save(Integer createId) throws Exception {
        CreateDespatchPlan createDespatchPlan=new CreateDespatchPlan();
        createDespatchPlan.setCreateId(createId);
        int insert = createDespatchPlanMapper.insert(createDespatchPlan);
        if(insert>0){
            List<CreateDistributeSku> list = createDistributeSkuService.findByCreateId(createId);
            for(CreateDistributeSku createDistributeSku:list){
                CreateDespatchSku createDespatchSku=new CreateDespatchSku();
                BeanUtils.copyProperties(createDistributeSku,createDespatchSku);

                createDespatchSkuService.save(createDespatchSku);
            }
        }
        return insert;
    }

    public void getRate(CreateDespatchSku createDespatchSku) throws Exception {
        CreatePlan createPlan = createPlanService.findById(createDespatchSku.getCreateId());
        Integer createSkuId = createDespatchSku.getCreateSkuId();
        CreateSku createSku = createSkuService.findById(createSkuId);
        Product product = productService.findBySku(createSku.getCreateSku());
        if(product.getProductSku().equals("V6025PK")){
            System.out.println(product.getProductCode());
        }
        String HsCode = removeInvisibleCharacters(product.getProductCode());
        if(null==product.getProductCode()){
            throw new RuntimeException("获取HSCODE信息异常！请检查SKU:"+createSku.getCreateSku());
        }
        TaxRate tax = taxRateService.findByCountryCode(createPlan.getCreatePlanCountry(), HsCode);
        if(null==tax){
            throw new RuntimeException("获取报关税率异常！请重新检查HSCODE:"+product.getProductCode()+";SKU:"+product.getProductSku());
        }
        createDespatchSku.setCreateCustomRate(tax.getClearRate());
        createDespatchSku.setCreatePercent(tax.getCustomsRate());
    }

    private static String removeInvisibleCharacters(String input) {
        // \\p{C} 匹配 Unicode 控制字符
        // \\p{Z} 匹配所有空白字符，包括零宽度空格
        // 组合成一个正则表达式来去除所有不可见字符
        return input.replaceAll("[\\p{C}\\p{Z}]", "");
    }
    @Transactional(rollbackFor = Exception.class)
    public void getMoney(CreateDespatchSku createDespatchSku,String period) throws Exception{
        CreatePlan createPlan = createPlanService.findById(createDespatchSku.getCreateId());
        String createPlanCountry =createPlan.getCreatePlanCountry();
        Coefficient coefficient = coefficientService.findByCountry(createPlanCountry);
        if (null==coefficient){
            throw new RuntimeException("获取申报系数信息异常！");
        }

        if(null==createDespatchSku.getErpProducePrice()){
            throw new RuntimeException("获取采购单报价信息异常！");
        }
        switch (createPlanCountry){
            case "US":
                getUSMoney(createDespatchSku,coefficient,period);
                break;
            case "AU":
                getUSMoney(createDespatchSku,coefficient,period);
                break;
            case "UK":
                getEUMoney(createDespatchSku,coefficient);
                break;
            case "DE":
                getEUMoney(createDespatchSku,coefficient);
                break;
            case "FR":
                getEUMoney(createDespatchSku,coefficient);
                break;
            case "IT":
                getEUMoney(createDespatchSku,coefficient);
                break;
            case "ES":
                getEUMoney(createDespatchSku,coefficient);
                break;
            case "CA":
                getCAMoney(createDespatchSku,coefficient);
                break;
            case "JP":
                getJPMoney(createDespatchSku,coefficient);
                break;
            case "PL":
                getUSMoney(createDespatchSku,coefficient,period);
                break;
            default:
                throw new RuntimeException("暂无获取到费用相关信息!");
        }
    }


    public void getCAMoney(CreateDespatchSku createDespatchSku,Coefficient coefficient){
        ExchangeRate rate = exchangeRateService.findByFromName("CNY", "CAD");
        //报关金额
        createDespatchSku.setCreateMoney(createDespatchSku.getErpProducePrice()/
                rate.getRatePercent()*
                createDespatchSku.getCreateNumber());
        //清关金额
        createDespatchSku.setCreateCustomRate(createDespatchSku.getCreateCustomRate()/100);
        createDespatchSku.setCreateCustomMoney(
                createDespatchSku.getErpProducePrice()/
                        rate.getRatePercent()*
                        coefficient.getCoefficientCoef()*
                        createDespatchSku.getCreateNumber());
        //关税
        createDespatchSku.setCreateCustomTax(
                (createDespatchSku.getErpProducePrice()*
                        coefficient.getCoefficientCoef()/
                        rate.getRatePercent()*
                        createDespatchSku.getCreateCustomRate())*
                        createDespatchSku.getCreateNumber());
        //关税(人民币)
        createDespatchSku.setCreateCustomTaxCny(rate.getRatePercent()*createDespatchSku.getCreateCustomTax());

    }

    public void getUSMoney(CreateDespatchSku createDespatchSku,Coefficient coefficient,String period){
        ExchangeRate rate = exchangeRateService.findByFromName("CNY", "USD");
        ExchangeRateRecord rateRecord = exchangeRateRecordService.findByPeriod(rate.getId(), period);
        if(null!=rateRecord){
            rate.setRatePercent(rateRecord.getRatePercent());
        }
        //获取采购单是美金还是人民币
        Produce detail = produceService.findIdByPo(createDespatchSku.getErpProducePo());
        if(null!=detail && detail.getProduceMoneyType().equals("美金")){
            ProduceDetail produceDetail = produceDetailService.findById(createDespatchSku.getCreateProduceId());
            createDespatchSku.setErpProducePrice(produceDetail.getProducePrice()*rate.getRatePercent());
            createDespatchSku.setErpProduceUnitPrice(produceDetail.getProduceUnitPrice()*rate.getRatePercent());
        }
        //报关金额
        createDespatchSku.setCreateMoney(createDespatchSku.getErpProducePrice()/
                                         rate.getRatePercent()*
                                         createDespatchSku.getCreateNumber());
        //清关金额
        createDespatchSku.setCreateCustomRate(createDespatchSku.getCreateCustomRate()/100);
        createDespatchSku.setCreateCustomMoney(
                createDespatchSku.getErpProducePrice()/
                        rate.getRatePercent()*
                        coefficient.getCoefficientCoef()*
                        createDespatchSku.getCreateNumber());
        //关税
        createDespatchSku.setCreateCustomTax(createDespatchSku.getErpProducePrice()*
                coefficient.getCoefficientCoef()/rate.getRatePercent()*
                (createDespatchSku.getCreateCustomRate() + 0.004714) *
                createDespatchSku.getCreateNumber());

        CoefficientSku co = coefficientSkuService.findBySku(createDespatchSku.getCreateSku(), createDespatchSku.getCreateChannelName());
        if(null != co){
            createDespatchSku.setCreateCustomTax(co.getCoefficientCoef()*createDespatchSku.getCreateCustomTax());
            createDespatchSku.setCreateCustomMoney(co.getCoefficientCoef()*createDespatchSku.getCreateCustomMoney());
        }
        //关税(人民币)
        createDespatchSku.setCreateCustomTaxCny(rate.getRatePercent()*createDespatchSku.getCreateCustomTax());

    }

    public void getEUMoney(CreateDespatchSku createDespatchSku,Coefficient coefficient){
        ExchangeRate rate = exchangeRateService.findByFromName("CNY", "EUR");
        if(null==rate){
            throw new RuntimeException("暂未查询到欧洲汇率信息");
        }
        //报关金额
        createDespatchSku.setCreateMoney(createDespatchSku.getErpProducePrice()/
                rate.getRatePercent()*
                createDespatchSku.getCreateNumber());
        //清关金额
        createDespatchSku.setCreateCustomRate(createDespatchSku.getCreateCustomRate()/100);
        createDespatchSku.setCreateCustomMoney(
                createDespatchSku.getErpProducePrice()/
                        rate.getRatePercent()*
                        coefficient.getCoefficientCoef()*
                        createDespatchSku.getCreateNumber());
        //关税
        createDespatchSku.setCreateCustomTax((
                createDespatchSku.getErpProducePrice()*
                        coefficient.getCoefficientCoef()/
                        rate.getRatePercent()*
                        createDespatchSku.getCreateCustomRate()*
                        createDespatchSku.getCreateNumber())+(createDespatchSku.getCreateCustomFreight()/rate.getRatePercent()
                *createDespatchSku.getCreateCustomRate()));
        //关税(人民币)
        createDespatchSku.setCreateCustomTaxCny(rate.getRatePercent()*createDespatchSku.getCreateCustomTax());

    }

    public void getJPMoney(CreateDespatchSku createDespatchSku,Coefficient coefficient){
        ExchangeRate rate = exchangeRateService.findByFromName("CNY", "JPY");
        if(null==rate){
            throw new RuntimeException("暂未查询到日本汇率信息");
        }
        //报关金额
        createDespatchSku.setCreateMoney(createDespatchSku.getErpProducePrice()/
                rate.getRatePercent()*
                createDespatchSku.getCreateNumber());
        //清关金额
        createDespatchSku.setCreateCustomRate(createDespatchSku.getCreateCustomRate()/100);
        createDespatchSku.setCreateCustomMoney(
                createDespatchSku.getErpProducePrice()/
                        rate.getRatePercent()*
                        coefficient.getCoefficientCoef()*
                        createDespatchSku.getCreateNumber());
        //关税
        createDespatchSku.setCreateCustomTax(
                createDespatchSku.getErpProducePrice()*
                        coefficient.getCoefficientCoef()/
                        rate.getRatePercent()*
                        createDespatchSku.getCreateCustomRate()*
                        createDespatchSku.getCreateNumber());
        //关税(人民币)
        createDespatchSku.setCreateCustomTaxCny(rate.getRatePercent()*createDespatchSku.getCreateCustomTax());
    }


    @Override
    public CreateDespatchPlan findByCreateId(Integer createId) {
        return createDespatchPlanMapper.findByCreateId(createId);
    }

    @Override
    public List<CreateDespatchPlan> findByCnd(CreateDespatchPlan createDespatchPlan) {
        return createDespatchPlanMapper.findByCnd(createDespatchPlan);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int usave(CreateDespatchPlan createDespatchPlan) throws Exception {
        String createSkuId = createDespatchPlan.getCreateSkuId();
        String despatchSupplier = createDespatchPlan.getDespatchSupplier();
        Integer despatchPort = createDespatchPlan.getDespatchPort();
        Integer despatchDest = createDespatchPlan.getDespatchDest();
        Integer despatchStore = createDespatchPlan.getDespatchStore();
        String despatchDate = createDespatchPlan.getDespatchDate();
        String createPeriod = createDespatchPlan.getCreatePeriod();
        Double freight = createDespatchPlan.getDespatchFreight();
        createDespatchPlan=createDespatchPlanMapper.findByCreateId(createDespatchPlan.getCreateId());
        createDespatchPlan.setDespatchPort(despatchPort);
        createDespatchPlan.setDespatchDest(despatchDest);
        createDespatchPlan.setDespatchStore(despatchStore);
        createDespatchPlan.setDespatchDate(despatchDate);
        createDespatchPlan.setCreatePeriod(createPeriod);
        createDespatchPlan.setDespatchFreight(freight);
        //计算运费
        updateTotal(createDespatchPlan);
        //分摊运费
        updateSkuFreight(createDespatchPlan);
        createDespatchPlan.setDespatchSupplier(despatchSupplier);
        createDespatchPlan.setCreateSkuId(createSkuId);
        return createDespatchPlanMapper.update(createDespatchPlan);
    }

    @Override
    public int updateTotal(Integer createId) {
        Integer boxNumber = createPackingSkuService.findBoxNumberByCreateId(createId);
        if (null == boxNumber) {
            return createDespatchPlanMapper.updateTotal(createId);
        } else {
            createDespatchPlanMapper.updateTotal(createId);
            return createDespatchPlanMapper.updateBoxNumberByCreateId(boxNumber, createId);
        }
    }

    @Override
    public int delete(Integer createId) {
        return createDespatchPlanMapper.delete(createId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int change(CreateDespatchSku createDespatchSku) {

        CreateDespatchSku despatchSku = createDespatchSkuService.findById(createDespatchSku.getId());
        //获取到分配信息
        CreateDistributeSku distributeSku = createDistributeSkuService.findByDetail(despatchSku.getCreateId(),
                despatchSku.getCreateSkuId(),
                despatchSku.getCreateProduceId(),
                despatchSku.getCreateNumber());

        distributeSku.setCreateNumber(createDespatchSku.getCreateNumber());
        //更新计划数量
        createDistributeSkuService.usave(distributeSku);

        //发运更新数量
        createDespatchSkuService.usave(createDespatchSku);

        //采购在产ID
        Integer createProduceId = despatchSku.getCreateProduceId();

        //原先的数量
        Integer skuNumber = createDespatchSku.getSkuNumber();

        //获取修改后的数量
        Integer createNumber = createDespatchSku.getCreateNumber();

        ProduceDetail produceDetail = produceDetailService.findById(createProduceId);
        Integer produceUse = produceDetail.getProduceUse();


        if(createNumber==0){
            produceUse=produceUse-skuNumber;
        }else{
            produceUse=produceUse-(skuNumber-createNumber);
        }
        return  produceDetailService.updateUseNumber(produceUse,createProduceId);
    }

    @Override
    public Integer updateBoxNumberByCreateId(Integer boxNumber, Integer id) {
        return createDespatchPlanMapper.updateBoxNumberByCreateId(boxNumber, id);
    }


    /**
     * 更新运费
     * @param createDespatchPlan
     * @throws Exception
     */
    void updateTotal(CreateDespatchPlan createDespatchPlan) throws Exception {
        //获取币种
        CreatePlan createPlan = createPlanService.findById(createDespatchPlan.getCreateId());
        String createPlanCountry = createPlan.getCreatePlanCountry();
        String currency = CountryMoneyEnum.getCountry(createPlanCountry);
        if (StringUtils.isBlank(currency)) {
            throw new Exception("暂未获取到货币信息！");
        } else {
            createDespatchPlan.setDespatchCurrency(currency);
        }
        //获取运费
        Freight freight = new Freight();
        freight.setFreightCabinetName(createPlan.getCreatePlanCabinetName());
        freight.setFreightTrans(createPlan.getCreatePlanTransport());
        freight.setFromPortId(createDespatchPlan.getDespatchPort());
        freight.setToWareId(createDespatchPlan.getDespatchStore());
        freight.setToPortId(createDespatchPlan.getDespatchDest());
        Freight f = freightService.findFreight(freight);
        if (null == f) {
            throw new RuntimeException("暂未获取到相关运费信息！");
        } else if(StringUtils.isBlank(f.getFreightType())){
            throw new RuntimeException("暂未获取到分摊方式,请先维护！");
        } else {
            //根据分摊方式计算运费
            String freightType = f.getFreightType();
            CreateDespatchPlan despatchPlan = createDespatchPlanMapper.findByCreateId(createDespatchPlan.getCreateId());
            if (freightType.equals("整柜")) {
                createDespatchPlan.setDespatchFreight(f.getFreightTotal());
            } else if ( freightType.equals("体积")) {
                createDespatchPlan.setDespatchFreight(despatchPlan.getCreatePlanVolume() * f.getFreightTotal());
            } else if(freightType.equals("重量")){
                createDespatchPlan.setDespatchFreight(despatchPlan.getCreateWeightTotal() * f.getFreightTotal());
            }
        }
    }
    /**
     * 分摊运费SKU
     * @param createDespatchPlan
     */
    @Transactional(rollbackFor = Exception.class)
    public void  updateSkuFreight(CreateDespatchPlan createDespatchPlan) throws Exception{
        List<CreateDespatchSku> list = createDespatchSkuService.findByCreateId(createDespatchPlan.getCreateId());
        CreatePlan createPlan = createPlanService.findById(createDespatchPlan.getCreateId());
        //获取运费
        Freight freight = new Freight();
        freight.setFreightCabinetName(createPlan.getCreatePlanCabinetName());
        freight.setFreightTrans(createPlan.getCreatePlanTransport());
        freight.setFromPortId(createDespatchPlan.getDespatchPort());
        freight.setToWareId(createDespatchPlan.getDespatchStore());
        freight.setToPortId(createDespatchPlan.getDespatchDest());
        Freight f = freightService.findFreight(freight);
        for(CreateDespatchSku createDespatchSku:list){
            //如果空运按体积分摊
            if(f.getFreightType().equals("体积")){
                //按体积分摊
                double fre = createDespatchPlan.getDespatchFreight() / createDespatchPlan.getCreatePlanVolume();
                createDespatchSku.setCreateCustomFreight(fre*createDespatchSku.getCreateVolumeTotal());

            }else if(f.getFreightType().equals("重量")){
                double fre = createDespatchPlan.getDespatchFreight() / createDespatchPlan.getCreateWeightTotal();
                createDespatchSku.setCreateCustomFreight(fre*createDespatchSku.getCreateWeightTotal());
            }else if(f.getFreightType().equals("整柜")){
                double fre = createDespatchPlan.getDespatchFreight() / createDespatchPlan.getCreateWeightTotal();
                createDespatchSku.setCreateCustomFreight(fre*createDespatchSku.getCreateWeightTotal());
            }
            //获取税率
            getRate(createDespatchSku);
            //获取费用
            getMoney(createDespatchSku,createDespatchPlan.getCreatePeriod());
            createDespatchSkuService.usave(createDespatchSku);
        }
        createDespatchPlan.setFreightType(f.getFreightType());
    }
}
